/* os_util.c : os file operation
 * CopyRight (C) 2006  dgnbbs
 * drangon_zhou@21cn.com
 * 2006-10
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "os_file.h"

#include <sys/file.h>
#include <fcntl.h>

os_file_t os_file_open( const char * fname )
{
	int fd;

	ASSERT( fname != NULL && fname[0] != '\0' );

	if( (fd = open( fname, O_RDWR | O_CREAT, 0660 )) < 0 ) {
		PR_ERR( "open [%s] failed, errno %d", fname, errno );
		return (os_file_t)(-1);
	}
	return fd;
}

int os_file_close( os_file_t fd )
{
	if( close( fd ) < 0 ) {
		PR_ERR( "close fd %d failed, erno %d", fd, errno );
	}
	return 0;
}

int os_file_lock( os_file_t fd )
{
	if( flock( fd, LOCK_EX ) < 0 ) {
		PR_ERR( "flock %d failed, errno %d", fd, errno );
		return -1;
	}
	return 0;
}

int os_filelock_unlock( os_file_t fd )
{
	if( flock( fd, LOCK_UN ) < 0 ) {
		PR_ERR( "flock %d failed, errno %d", fd, errno );
	}
	return 0;
}

int os_file_read( os_file_t fd, int64_t offset, char * buf, int32_t len )
{
	int ret, readlen = 0;

	ASSERT( fd >= 0 && offset >= 0 && buf != NULL && len > 0 );

	if( lseek( fd, offset, SEEK_SET ) == -1 ) {
		PR_ERR( "fd %d lseek %lld failed, errno %d", fd, offset, errno );
		return -1;
	}
	while( readlen < len ) {
		ret = read( fd, buf + readlen, len - readlen );
		if( ret == 0 )
			break;
		if( ret < 0 ) {
			if( errno == EINTR || errno == EAGAIN )
				continue;
			PR_ERR( "read fd %d off %lld file failed, errno %d", fd, offset, errno );
			return -1;
		}
		readlen += ret;
	}
	return readlen;
}

int os_file_write( os_file_t fd, int64_t offset, const char * buf, int32_t len )
{
	int ret, wlen = 0;

	ASSERT( fd >= 0 && offset >= 0 && buf != NULL && len > 0 );

	if( lseek( fd, offset, SEEK_SET ) == -1 ) {
		PR_ERR( "fd %d lseek %lld failed, errno %d", fd, offset, errno );
		return -1;
	}
	while( wlen < len ) {
		ret = write( fd, (char *)buf + wlen, len - wlen );
		if( ret == 0 )
			break;
		if( ret < 0 ) {
			if( errno == EINTR || errno == EAGAIN )
				continue;
			PR_ERR( "write fd %d off %lld file failed, errno %d", fd, offset, errno );
			return -1;
		}
		wlen += ret;
	}
	return wlen;
}

